package com.net.xpay.core.service.impl;

import com.google.common.collect.Lists;
import com.net.xpay.common.domain.User;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.service.TaokeDetectionService;
import com.net.xpay.core.service.api.TaokedingdanApi;
import com.net.xpay.core.validator.TaokeDetectionValidator;
import com.net.common.annotation.WriteTransactional;
import com.net.common.exception.BusinessException;
import com.net.xpay.core.domain.AccountDetail;
import com.net.xpay.core.domain.TaokeDetectionBatch;
import com.net.xpay.core.domain.TaokeDetectionRecord;
import com.net.xpay.core.domain.UserAccount;
import com.net.xpay.core.enums.AccountBillType;
import com.net.xpay.core.enums.TaokeDetectionBatchStatus;
import com.net.xpay.core.enums.TaokeStatus;
import com.net.xpay.core.helper.AccountDetailHelper;
import com.net.xpay.core.manager.TaokeDetectionBatchManager;
import com.net.xpay.core.manager.TaokeDetectionRecordManager;
import com.net.xpay.core.manager.UserAccountManager;
import com.net.xpay.core.model.TaokeDetectionModel;
import com.net.xpay.core.model.TaokeResponse;
import com.net.xpay.core.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 2020/6/6 11:11

 */
@Slf4j
@Service
@WriteTransactional
public class TaokeDetectionServiceImpl implements TaokeDetectionService {

    @Autowired
    private TaokeDetectionValidator taokeDetectionValidator;

    @Autowired
    private TaokeDetectionRecordManager taokeDetectionRecordManager;

    @Autowired
    private TaokedingdanApi taokedingdanApi;

    @Autowired
    private AccountService accountService;

    @Autowired
    private UserAccountManager userAccountManager;

    @Autowired
    private AccountDetailHelper accountDetailHelper;

    @Autowired
    private TaokeDetectionBatchManager taokeDetectionBatchManager;

    @Override
    public TaokeDetectionRecord detection(User user, TaokeDetectionModel detectionModel) {
        UserAccount userAccount = userAccountManager.getByIdWithLock(user.getId());
        if (userAccount.getMoneyLeft() - user.getTaokeUnitPrice() < 0) {
            throw new BusinessException(PoseidonErrorCode.MONEY_NOT_ENOUGH, "余额不足，请先充值~");
        }

        taokeDetectionValidator.validateTaokeDetection(user, detectionModel);

        //查询是否有检测完成的记录
        TaokeDetectionRecord record = taokeDetectionRecordManager.findByTid(user.getId(), detectionModel.getTid());
        if (record != null && Lists.newArrayList(TaokeStatus.IS_TK, TaokeStatus.NOT_TK).contains(record.getStatus())) {
            return record;
        }

        if (record != null) {
            record.setWw(detectionModel.getWw());
            record.setBuyerMobile(detectionModel.getBuyerMobile());
        } else {
            record = TaokeDetectionRecord.getInstance(user, detectionModel);
        }
        //开始查询
        TaokeResponse resp = taokedingdanApi.getOrderState(detectionModel.getTid());
        if (resp.isSuccess()) {
            if (resp.getState() == 0) {
                record.setStatus(TaokeStatus.NOT_TK);
            } else if (resp.getState() == 1) {
                record.setStatus(TaokeStatus.IS_TK);
            }

        } else {
            record.setStatus(TaokeStatus.FAILED);
        }

        if (record.getId() == null) {
            taokeDetectionRecordManager.save(record);
        } else {
            taokeDetectionRecordManager.update(record);
        }

        if (resp.isSuccess()) {
            //检测成功扣钱
            deductMoneyAfterSuccessDetection(user, userAccount, record.getId());
        }

        return record;
    }

    @Override
    public TaokeDetectionBatch batchDetection(User merchant, Long batchId) {
        TaokeDetectionBatch batch = taokeDetectionBatchManager.findById(merchant.getId(), batchId);
        if (batch == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "查询批次不存在");
        }
        if (batch.getStatus() != TaokeDetectionBatchStatus.WAIT) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "批次不是待查询状态");
        }

        UserAccount account = userAccountManager.getByIdWithLock(merchant.getId());
        if (account.getMoneyLeft() - batch.getTaokePrice() < 0) {
            throw new BusinessException(PoseidonErrorCode.MONEY_NOT_ENOUGH, "余额不足，请先充值");
        }

        //开始批量检测 查一条扣一条
        List<TaokeDetectionRecord> recordList = taokeDetectionRecordManager.listByBatchId(merchant.getId(), batchId);

        long successCount = 0L;
        for (TaokeDetectionRecord record : recordList) {
            try {
                doDetection(merchant, record);
                if (record.getStatus() != TaokeStatus.WAIT && record.getStatus() != TaokeStatus.FAILED) {
                    successCount++;
                }
            } catch (Exception e) {
                log.error("batchDetection error|id={}|merchantId={}", record.getId(), merchant.getId(), e);
            }
        }

        batch.setSuccessCount(successCount);
        batch.setFailCount(batch.getTotalCount() - batch.getSuccessCount());
        if (batch.getSuccessCount() != 0L) {
            batch.setStatus(TaokeDetectionBatchStatus.SUCCESS);
        } else {
            batch.setStatus(TaokeDetectionBatchStatus.FAIL);
        }

        taokeDetectionBatchManager.update(batch);

        return batch;
    }

    private void doDetection(User user, TaokeDetectionRecord record) {
        //已经查询过的且不是查询失败的不再查询
        if (record.getStatus() != TaokeStatus.WAIT && record.getStatus() != TaokeStatus.FAILED) {
            return;
        }

        UserAccount userAccount = userAccountManager.getByIdWithLock(user.getId());
        if (userAccount.getMoneyLeft() - user.getTaokeUnitPrice() < 0) {
            record.setStatus(TaokeStatus.FAILED);
            record.setErrorMessage("余额不足，请先充值");
            return;
        }

        //开始查询
        TaokeResponse resp = taokedingdanApi.getOrderState(record.getTid());
        if (resp.isSuccess()) {
            if (resp.getState() == 0) {
                record.setStatus(TaokeStatus.NOT_TK);
            } else if (resp.getState() == 1) {
                record.setStatus(TaokeStatus.IS_TK);
            }

        } else {
            record.setStatus(TaokeStatus.FAILED);
        }

        taokeDetectionRecordManager.update(record);

        if (resp.isSuccess()) {
            //检测成功扣钱
            deductMoneyAfterSuccessDetection(user, userAccount, record.getId());
        }
    }

    private void deductMoneyAfterSuccessDetection(User user, UserAccount userAccount, Long recordId) {
        AccountDetail accountDetail = AccountDetail.getInstance(user.getId(), recordId);
        accountDetailHelper.initCommonAccountDetail(accountDetail, AccountBillType.TAOKE_DETECTION, - user.getTaokeUnitPrice(), "");

        accountService.onPay(user, userAccount, accountDetail);

    }
}
